﻿#include "stdafx.h"
/// Copyright 2012, Alex Averian, Yonan Research
/// Released under BSD Licence

#include "qbitmap.h"
using namespace micro::gui;




bool QBitmap::SaveImage( QString & path )
{
    QSize sz = GetSize();

    BITMAPINFOHEADER   bi;

    bi.biSize = sizeof( BITMAPINFOHEADER );
    bi.biWidth = sz.cx;
    bi.biHeight = sz.cy;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ( ( sz.cx * bi.biBitCount + 31 ) / 32 ) * 4 * sz.cy;


    // Therefore, GlobalAlloc and LocalAlloc
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc( GHND, dwBmpSize );
    char * lpbitmap = ( char * )GlobalLock( hDIB );

    // Gets the "bits" from the bitmap and copies them into a buffer
    // which is pointed to by lpbitmap.

    HDC hdc = GetDC( nullptr );
    GetDIBits( hdc, 0,  sz.cy, lpbitmap, ( BITMAPINFO * )&bi, DIB_RGB_COLORS );
    ::ReleaseDC( nullptr, hdc );


    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );



    BITMAPFILEHEADER   bmfHeader = {0};
    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM

    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB;

    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = ( DWORD )sizeof( BITMAPFILEHEADER ) + ( DWORD )sizeof( BITMAPINFOHEADER );


    QFile fis;
    fis.Open( path, QFile::modeCreate | QFile::modeWrite );

    DWORD dwBytesWritten = 0;
    fis.Write( ( LPCVOID )&bmfHeader, sizeof( BITMAPFILEHEADER ), dwBytesWritten  );
    fis.Write( ( LPCVOID )&bi, sizeof( BITMAPINFOHEADER ), dwBytesWritten  );
    fis.Write( ( LPCVOID )lpbitmap, dwBmpSize, dwBytesWritten  );

    //Unlock and Free the DIB from the heap
    GlobalUnlock( hDIB );
    GlobalFree( hDIB );

    return true;
}




bool QBitmap::CopyToClipboard( )
{
    if ( !OpenClipboard( nullptr ) )
        return false;

    EmptyClipboard();

    QSize sz = GetSize();

    BITMAPINFOHEADER   bi;

    bi.biSize = sizeof( BITMAPINFOHEADER );
    bi.biWidth = sz.cx;
    bi.biHeight = sz.cy;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ( ( sz.cx * bi.biBitCount + 31 ) / 32 ) * 4 * sz.cy;
    bi.biSizeImage = dwBmpSize;

    // Therefore, GlobalAlloc and LocalAlloc
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc( GHND, dwBmpSize +  sizeof( BITMAPINFOHEADER )   );
    char * lpbitmap = ( char * )GlobalLock( hDIB );

    CopyMemory( lpbitmap, &bi, sizeof( BITMAPINFOHEADER ) );


    HDC hdc = GetDC( nullptr );
    GetDIBits( hdc, 0,  sz.cy, lpbitmap + sizeof( BITMAPINFOHEADER ), ( BITMAPINFO * )&bi, DIB_RGB_COLORS );
    ::ReleaseDC( nullptr, hdc );

    if ( hDIB )
        SetClipboardData( CF_DIB, hDIB );



    //Unlock and Free the DIB from the heap
    GlobalUnlock( hDIB );
    GlobalFree( hDIB );


    CloseClipboard();
    return true;
}

